/*---------------------------------------------------------------------------*/
#include <QtGui>
#include "BrowserBox.h"
#include "Utils.h"
#include <iostream>
#include "FileSortFilterModel.h"
#include "MenuMaker.h"
#include "Threads.h"
#include "RegExp.h"
#include "FileOps.h"
/*---------------------------------------------------------------------------*/
using namespace std;
/*---------------------------------------------------------------------------*/
/*  BrowserBox class                                                     */
/*---------------------------------------------------------------------------*/
BrowserBox::BrowserBox() : QTreeView()
{
	bShowHidden = false;
	bShowSwapFiles = false;
	
	init();
}
/*---------------------------------------------------------------------------*/
BrowserBox::~BrowserBox()
{
	if(browser) delete browser;	
	if(regExp) delete regExp;
}
/*---------------------------------------------------------------------------*/
void BrowserBox::init()
{
	DEBUGMSG("BrowserBox::init()");
	
	// init
	
	browser = new FileBrowser(getenv("PWD"));
	
	
	//browser->getRootNode()->show();
	browser->fillCurrentNode();
	currentNode = browser->getCurrentNode();
	
	// props
	model = new FileSortFilterModel();
	setModel( model );

	
	
	setRootIsDecorated(false);
	setAlternatingRowColors(true);
	setSortingEnabled(true);
	
	setColumnHidden(COLUMN_HIDDEN,true);
	setColumnWidth(COLUMN_ICON,22);
	
	setContentsMargins(2,2,2,2);
	
	
	header()->resizeSection( COLUMN_FILENAME , 575 );
	header()->resizeSection( COLUMN_EXT , 50 );
	header()->resizeSection( COLUMN_SIZE , 100 );
	header()->resizeSection( COLUMN_TYPE , 20 );
	

	// connections
	connect(this, SIGNAL( clicked ( const QModelIndex& ) ), this, SLOT( clicked ( const QModelIndex& )  ) );
	connect(this, SIGNAL( doubleClicked ( const QModelIndex& ) ), this, SLOT( doubleClicked ( const QModelIndex& )  ) );
	
	// icons
	icons[ICON_FILE].addFile("/usr/share/gfm/images/file.png");
	icons[ICON_FOLDER].addFile("/usr/share/gfm/images/folder.png");
	
	
	sortByColumn(COLUMN_TYPE,Qt::AscendingOrder);
	
	
	// multiple selection
	setSelectionMode( QAbstractItemView::ExtendedSelection );
	
	// drag & drop
	setDragEnabled(true);
	setDragDropMode( QAbstractItemView::DragDrop );
	setAcceptDrops(true);
	
	
	regExp = NULL;
}
/*---------------------------------------------------------------------------*/    
void BrowserBox::clear()
{
	model->removeRows(0, model->rowCount());
	model->sort(0,Qt::AscendingOrder); // sort column0 to avoid insertRow crash!
}
/*---------------------------------------------------------------------------*/
void BrowserBox::fillFromCurrentNode()
{
	// fill 
	fillList(currentNode);
}
/*---------------------------------------------------------------------------*/
void BrowserBox::fillList(FileNode *fn)
{
	
	if( !fn->isFilled() ) browser->fillNode(fn);

	
	FileNode *child = fn->getFirstChild();

	clear();
	
	if(fn->getParent()) addItem("..", fn->getParent() );


	// browse each child
	while( child )
	{
		
		// show hidden files?
		if( bShowHidden || child->getName()[0] != '.' )
		{
		
			// show swap files?
			if( bShowSwapFiles || Utils::getLastChar( child->getName() ) != '~' )
			{
				// TODO: apply filters!
				
				if( regExp )
				{
					if( regExp->match( child->getName() ) )	addItem( child );
				}
				else
				{
					addItem( child );
				}
			}			
						
		}
		

		
		
		child = fn->getNextChild();
	}

	currentNode = fn;
	emit directoryChanged( fn );


	
	//this->resizeColumnToContents(COLUMN_FILENAME);
	this->sortByColumn(COLUMN_FILENAME, Qt::AscendingOrder );
}
/*---------------------------------------------------------------------------*/
FileBrowser *BrowserBox::getBrowser()
{
	return browser;
}
/*---------------------------------------------------------------------------*/
string BrowserBox::getCurrentPath()
{
	return currentNode->getAbsolutePath();
}
/*---------------------------------------------------------------------------*/
FileNode *BrowserBox::getCurrentNode()
{
	return currentNode;
}
/*---------------------------------------------------------------------------*/
void BrowserBox::clicked( const QModelIndex & mi )
{
	// if right click	
	if( lastMouseEvent->button() == Qt::RightButton )
	{
		MenuMaker *menu = new MenuMaker(&getSelectedFiles(), this);
		menu->show();
	}
}
/*---------------------------------------------------------------------------*/
void BrowserBox::doubleClicked( const QModelIndex & mi )
{
	MenuMaker *menu = new MenuMaker(&getSelectedFiles(), this);
	menu->runAction();

}
/*---------------------------------------------------------------------------*/
void BrowserBox::addItem( FileNode *item )
{
	int id = model->rowCount();
	string strtemp = "";
	model->insertRow(0); // crash if column 0 is not selected
	if(item->getType() == 8) strtemp = Utils::formatSize( item->getSize(), 0 );	
	
	
	model->setData(model->index(id, COLUMN_HIDDEN), (uint)item  );
	model->setData(model->index(id, COLUMN_FILENAME), QString( item->getName().c_str() ) );
	model->setData(model->index(id, COLUMN_EXT), QString( item->getExtension().c_str() ) );
	model->setData(model->index(id, COLUMN_SIZE), QString(strtemp.c_str() ) );
	model->setData(model->index(id, COLUMN_ICON), *getIconFromFileNode(item), Qt::DecorationRole );
	model->setData(model->index(id, COLUMN_TYPE), QString::number(  item->getType() ) );
	
	
	//item(id)->setDropEnabled(true);
	
	//indexWidget( model->index(id,COLUMN_ICON) )
}
/*---------------------------------------------------------------------------*/
void BrowserBox::addItem( const char *str ,  FileNode *item )
{
	int id = model->rowCount();
	model->insertRow(0);
	model->setData(model->index(id, COLUMN_HIDDEN), (uint)item  );
	model->setData(model->index(id, COLUMN_FILENAME), QString( str ) );
}
/*---------------------------------------------------------------------------*/    
void BrowserBox::edit ( const QModelIndex & index )
{
	DEBUGMSG("BrowserBox::edit()");
}
/*---------------------------------------------------------------------------*/   
void BrowserBox::showHidden( bool b )
{
	bShowHidden = b;
}
/*---------------------------------------------------------------------------*/   
void BrowserBox::showSwapFiles( bool b )
{
	bShowSwapFiles = b;
}
/*---------------------------------------------------------------------------*/   
void BrowserBox::goTo(char *path)
{
	browser->goToPath( path );
	fillList(browser->getCurrentNode());
}
/*---------------------------------------------------------------------------*/   
void BrowserBox::goHome()
{
	browser->goToPath( getenv("HOME") );
	fillList(browser->getCurrentNode());
}
/*---------------------------------------------------------------------------*/  
void BrowserBox::goParent()
{
	if(currentNode->getParent()) fillList(currentNode->getParent());
}
/*---------------------------------------------------------------------------*/  
void BrowserBox::refresh()
{
	browser->fillNode(currentNode,1,true);
	fillList(currentNode);
}
/*---------------------------------------------------------------------------*/  
QIcon *BrowserBox::getIconFromFileNode(FileNode *fn)
{

	if( fn->isFolder() )  return &icons[ICON_FOLDER];

	switch( fn->getType() )
	{
		case 0: return &icons[ICON_FOLDER];
		case 4: return &icons[ICON_FOLDER];
	}
	
	return &icons[ICON_FILE];
}
/*---------------------------------------------------------------------------*/  
FileNode *BrowserBox::getSelectedFile() // returns the first file only
{

	if( selectedIndexes().count() )
	{
		QVariant d = model->data( model->index( selectedIndexes()[0].row() , 0) );
		FileNode *fn = reinterpret_cast<FileNode*>(d.toUInt());

		return fn;
	}
	
	return NULL;
}
/*---------------------------------------------------------------------------*/  
vector<FileNode*> BrowserBox::getSelectedFiles()
{
	vector<FileNode*> vfn;
	
	for(int i =0; i < selectedIndexes().count(); i++)
	{

		QVariant d = model->data( model->index( selectedIndexes()[i].row() , 0) );
		FileNode *fn = reinterpret_cast<FileNode*>(d.toUInt());
	
		// check if already there
		bool exist = false;
		foreach( FileNode*, f, vfn )
		{
			if( (*f) == fn ) exist = true;
		}
		
		if(!exist)
		{
			vfn.push_back(fn);
		}
	}

	
	return vfn;
}
/*---------------------------------------------------------------------------*/  
void BrowserBox::setFilter(string str)
{
	if(regExp) delete regExp;
	
	regExp = new RegExp( str );
	
	fillFromCurrentNode();
}
/*---------------------------------------------------------------------------*/  
void BrowserBox::mousePressEvent ( QMouseEvent * event )
{
	QTreeView::mousePressEvent( event );
	
	// get last mouse event to get buttons
	lastMouseEvent = event;
}
/*---------------------------------------------------------------------------*/  
void BrowserBox::keyPressEvent( QKeyEvent *event )
{
	
	//DEBUGMSG( "BrowserBox::keyPressEvent() : " << event->key() );
	
	if( event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter )
	{
		if( getSelectedFile() )
		{
			MenuMaker *menu = new MenuMaker(&getSelectedFiles(), this);
			menu->runAction();
		}
		
	}
	else if( event->key() == Qt::Key_Up ||  event->key() == Qt::Key_Down )
	{
		QAbstractItemView::keyPressEvent( event );
	}
	else if( event->key() == Qt::Key_Delete )
	{
		FileOps::remove( getSelectedFiles() );	
	}
	else if( event->modifiers() == Qt::ControlModifier ) // Control pressed
	{
		switch( event->key() )
		{
			case Qt::Key_X:
			{
				FileOps::cut( getSelectedFiles() );
			}
			break;
		
			case Qt::Key_C:
			{
				FileOps::copy( getSelectedFiles() );
			}
			break;	
			
			case Qt::Key_V:
			{
				FileOps::paste( currentNode );
			}
			break;				
			
			case Qt::Key_F:
			{
				emit typing(NULL);
			}
			break;		

					
		}
	}
	else
	{
		
		emit typing(event);
	}
	
	
}
/*---------------------------------------------------------------------------*/
void BrowserBox::dropEvent ( QDropEvent * event )
{
	QString str = event->mimeData()->text();
	
	
	if( str.left(8) == "gfm.drag" )
	{
		QStringList data = str.mid(9).split(";");
		
		vector<FileNode*> vec;
		vec.clear();
			
		for(int i=0; i < data.count(); i++)
		{
			if( data[i] == "" ) break;
			
			FileNode *fn = new FileNode( data[i].toStdString() );
			
			vec.push_back(fn);

		

		}
		
		
		MenuMaker *menu = new MenuMaker();
		menu->setDropMenu( &vec, this );
		menu->show();
	
	}	
}
/*---------------------------------------------------------------------------*/
void BrowserBox::dragMoveEvent ( QDragMoveEvent * event )
{

}
/*---------------------------------------------------------------------------*/
void BrowserBox::dragEnterEvent ( QDragEnterEvent * event )
{
	
	QTreeView::dragEnterEvent(event);
	
	if (event->mimeData()->hasFormat("text/plain")) 
	{
		event->acceptProposedAction();
	}
}
/*---------------------------------------------------------------------------*/
void BrowserBox::startDrag(Qt::DropActions supportedActions)
{
 	QDrag *drag = new QDrag(this);
	QMimeData *mimeData = new QMimeData;


	QString msg = "gfm.drag:";
	msg += Utils::groupStringFiles( getSelectedFiles() ).c_str();


	mimeData->setText(msg);
	drag->setMimeData(mimeData);



	drag->exec( Qt::MoveAction );
}
/*---------------------------------------------------------------------------*/ 


